#version 330 core

in vec4 scam_vtx_cord;
in vec3 vtx_cord;
in vec3 vtx_norm;
in vec2 vtx_tex_cord;
// in vec4 light_space_cord;

out vec4 out_color;

struct Material {
    bool has_tex;
    bool has_norm_tex;
    bool has_light_tex;
    bool has_shicha_tex;
    sampler2D tex_unit_id;
    sampler2D norm_tex_unit_id;
    sampler2D light_tex_unit_id;
    sampler2D shicha_tex_unit_id;

    float shininess;
    vec3 material_color;
    vec3 specular_color;
};

struct Light {
    int type; // para=1 spot=2 point=3
    vec3 ambient_color;
    vec3 diffuse_color;
    vec3 specular_color;

    vec3 location;
    vec3 direction;
    float half_angle;    // degree
    sampler2D shdadow_map_unit_id;
};

uniform Material material;
uniform Light light;
uniform vec3 cam_location;

float ShadowCalculation(vec4 light_space_pos) {
    vec3 projCoords = light_space_pos.xyz / light_space_pos.w;
    //projCoords = projCoords * 0.5 + 0.5;
    projCoords = (projCoords * 0.5 + 0.5)*2; // !!!
    projCoords.z /= 2;

    float closestDepth = texture(light.shdadow_map_unit_id, projCoords.xy).r; 
    //float bias = max(0.05 * (1.0 - dot(vtx_norm, -light.direction)), 0.005);
    float bias = 0.005;
    float is_in_shadow = projCoords.z - bias > closestDepth ? 1.0 : 0.0;
    // return projCoords.z - closestDepth;
    return is_in_shadow;
}

vec3 phong_lighting(vec3 cur_color, float is_in_shadow) {
    vec3 ret_color = vec3(0.0, 0.0, 0.0);
    //ret_color = vec3(is_in_shadow);return ret_color;

    // 环境光照
    vec3 env_color = cur_color * light.ambient_color;

    // 漫反射光照：光线向量
    vec3 light_vec;
    if(light.type == 1) {   // 平行光
        light_vec = light.direction;
    }
    // else if(light.type == 2) { // 聚光灯
    //     light_vec = 
    // }
    else {
        // 不支持的光源类型
        return vec3(0.0, 0.99, 0.0);
    }

    // 漫反射光照：片段法向量
    vec3 norm_vec;
    if(material.has_norm_tex == true) {
        norm_vec = texture(material.norm_tex_unit_id, vtx_tex_cord).rgb;
        norm_vec = normalize(norm_vec * 2.0 - 1.0);
        norm_vec = normalize(norm_vec - normalize((vec3(0, 0, 1) - vec3(0, 1, 0))));
        // ret_color = vec4(norm_vec, 1.0);
        // return;
    }
    else {
        norm_vec = vtx_norm;
        // norm_vec = normalize(vtx_cord); // !!!
    }
    vec3 diffuse_color = max(dot(norm_vec, -light_vec), 0.0) * light.diffuse_color * cur_color;

    // 高光反射
    vec3 specular_color;
    vec3 view_dir = normalize(cam_location - vtx_cord);
    vec3 reflect_dir = normalize(reflect(light_vec, norm_vec));  // -light_vec
    float spec = pow(max(dot(view_dir, reflect_dir), 0.0), material.shininess);
    // return reflect_dir;

    //return light.specular_color * spec;

    if(material.has_light_tex) {
        specular_color = light.specular_color * spec * texture(material.light_tex_unit_id, vtx_tex_cord).rgb;
    }
    else{
        specular_color = light.specular_color * spec * material.specular_color;
    }

    float is_daytime = 1;
    if(light.location.y < 0) {
        is_daytime = 0;
    }

    ret_color = vec3(
        env_color + 
        (diffuse_color + specular_color) * (1 - is_in_shadow) * is_daytime
    );

    return ret_color;
}

void main() {

    // vec3 projCoords = scam_vtx_cord.xyz / scam_vtx_cord.w;
    // projCoords = projCoords * 0.5 + 0.5;
    // out_color = vec4(vec3(texture(light.shdadow_map_unit_id, projCoords.xy).r), 1); return;
    
    // out_color = vec4(0.9, 0.9, 0.9, 1.0); return;
    // out_color = vec4(vtx_tex_cord.x, vtx_tex_cord.y, 0.9, 1.0); return;

    vec3 color = vec3(0.0, 1.0, 0.0);
    if(material.has_tex) {
        color = texture(material.tex_unit_id, vtx_tex_cord).rgb;
    }
    else {
        color = material.material_color.rgb;
    }

    // out_color = vec4(color, 1.0); return;

    float is_in_shadow = ShadowCalculation(scam_vtx_cord);
    // if(is_in_shadow < 0) {out_color = vec4(1,0,0,1);return;}
    //  out_color = vec4(vec3(is_in_shadow), 1); return;
    vec3 phong_lighting_color = phong_lighting(color, is_in_shadow);
    out_color = vec4(phong_lighting_color, 1.0);
}
